package com.yuexia.yxim.client.client;

import com.yuexia.yxim.client.handler.ChatMsgHandler;
import com.yuexia.yxim.client.handler.ExceptionHandler;
import com.yuexia.yxim.client.handler.LoginResponceHandler;
import com.yuexia.yxim.common.code.ProtobufDecoder;
import com.yuexia.yxim.common.code.ProtobufEncode;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.concurrent.GenericFutureListener;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

/**
 * @Author: yue_xia
 * @Date: 2020/6/1 11:00 下午
 */
@Slf4j
@Service("nettyClient")
public class NettyClient {

    /**
     * 服务器地址
     */
    @Value("${server.host}")
    private String host;

    /**
     * 服务器端口
     */
    @Value("${server.port}")
    private int port;

    @Autowired
    private ChatMsgHandler chatMsgHandler;

    @Autowired
    private LoginResponceHandler loginResponceHandler;

    @Autowired
    private ExceptionHandler exceptionHandler;

    //连接异步监听
    private GenericFutureListener<ChannelFuture> conectdListener;

    private Bootstrap bootstrap;
    private EventLoopGroup eventLoopGroup;

    public NettyClient() {
        eventLoopGroup = new NioEventLoopGroup();
    }

    /**
     * 重连
     */
    public void doConnect() {
        try {
            bootstrap = new Bootstrap();
            bootstrap.group(eventLoopGroup)
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                    .remoteAddress(host, port);

            //设置设置通道初始化参数
            bootstrap.handler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel socketChannel) throws Exception {
                    ChannelPipeline pipeline = socketChannel.pipeline();
                    pipeline.addLast("decoder", new ProtobufDecoder());
                    pipeline.addLast("encoder", new ProtobufEncode());
                    pipeline.addLast("loginResponceHandler", loginResponceHandler);
                    pipeline.addLast("chatMsgHandler", chatMsgHandler);
                    pipeline.addLast("exceptionHandler", exceptionHandler);
                }
            });

            log.info("客户端开始连接...");
            ChannelFuture future = bootstrap.connect();
            future.addListener(conectdListener);
        } catch (Exception e) {
            log.error("客户端连接失败：{}", e.getMessage());
        }
    }

    public void close() {
        eventLoopGroup.shutdownGracefully();
    }
}
